"""
Unit tests for AdapterManager
"""

import pytest
import asyncio
from unittest.mock import Mock, AsyncMock, patch
from typing import Dict, Any

from app.adapters.manager import AdapterManager
from app.adapters.core import DataAdapter, HistoricalDataAdapter, AdapterError


class MockAdapter(DataAdapter):
    """Mock adapter for testing"""
    
    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.initialized = False
        self.cleaned_up = False
        self._healthy = True
    
    async def initialize(self) -> None:
        self.initialized = True
    
    async def cleanup(self) -> None:
        self.cleaned_up = True
    
    async def health_check(self) -> bool:
        return self._healthy


class MockHistoricalAdapter(HistoricalDataAdapter):
    """Mock historical adapter for testing"""
    
    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.initialized = False
        self.cleaned_up = False
    
    async def initialize(self) -> None:
        self.initialized = True
    
    async def cleanup(self) -> None:
        self.cleaned_up = True
    
    async def health_check(self) -> bool:
        return True
    
    async def query_bars(self, *args, **kwargs):
        return []
    
    async def query_ticks(self, *args, **kwargs):
        return []


@pytest.fixture
def mock_config():
    """Mock configuration object"""
    config = Mock()
    config.ADAPTERS_CONFIG = {
        'mock1': {
            'enabled': True,
            'class': 'tests.test_adapter_manager.MockAdapter',
            'config': {'param1': 'value1'}
        },
        'mock2': {
            'enabled': False,  # Disabled
            'class': 'tests.test_adapter_manager.MockAdapter',
            'config': {'param2': 'value2'}
        },
        'historical': {
            'enabled': True,
            'class': 'tests.test_adapter_manager.MockHistoricalAdapter',
            'config': {'param3': 'value3'}
        }
    }
    return config


@pytest.mark.asyncio
class TestAdapterManager:
    """Tests for AdapterManager"""
    
    async def test_initialize_adapters(self, mock_config):
        """Test initializing adapters from configuration"""
        manager = AdapterManager(config=mock_config)
        await manager.initialize()
        
        try:
            # Check that enabled adapters were initialized
            assert 'mock1' in manager.adapters
            assert 'historical' in manager.adapters
            
            # Check that disabled adapter was not initialized
            assert 'mock2' not in manager.adapters
            
            # Check that adapters were initialized properly
            assert manager.adapters['mock1'].initialized is True
            assert manager.adapters['historical'].initialized is True
            
        finally:
            await manager.cleanup()
    
    async def test_get_adapter(self, mock_config):
        """Test getting adapters by name"""
        manager = AdapterManager(config=mock_config)
        await manager.initialize()
        
        try:
            # Get existing adapter
            adapter = manager.get_adapter('mock1')
            assert adapter is not None
            assert isinstance(adapter, MockAdapter)
            
            # Get non-existent adapter
            adapter = manager.get_adapter('nonexistent')
            assert adapter is None
            
        finally:
            await manager.cleanup()
    
    async def test_list_adapters(self, mock_config):
        """Test listing all adapters"""
        manager = AdapterManager(config=mock_config)
        await manager.initialize()
        
        try:
            names = manager.list_adapters()
            assert 'mock1' in names
            assert 'historical' in names
            assert len(names) == 2  # Only enabled adapters
            
        finally:
            await manager.cleanup()
    
    async def test_get_historical_adapters(self, mock_config):
        """Test getting historical adapters"""
        manager = AdapterManager(config=mock_config)
        await manager.initialize()
        
        try:
            historical = manager.get_historical_adapters()
            assert len(historical) == 1
            assert isinstance(historical[0], HistoricalDataAdapter)
            
        finally:
            await manager.cleanup()
    
    async def test_cleanup(self, mock_config):
        """Test cleanup of adapters"""
        manager = AdapterManager(config=mock_config)
        await manager.initialize()
        
        adapters = list(manager.adapters.values())
        
        await manager.cleanup()
        
        # Check that all adapters were cleaned up
        for adapter in adapters:
            assert adapter.cleaned_up is True
        
        # Check that adapter registry was cleared
        assert len(manager.adapters) == 0
    
    async def test_health_check(self, mock_config):
        """Test health check of all adapters"""
        manager = AdapterManager(config=mock_config)
        await manager.initialize()
        
        try:
            health_status = await manager.health_check()
            
            assert 'mock1' in health_status
            assert 'historical' in health_status
            assert health_status['mock1'] is True
            assert health_status['historical'] is True
            
        finally:
            await manager.cleanup()
    
    async def test_reload_adapter(self, mock_config):
        """Test reloading a specific adapter"""
        manager = AdapterManager(config=mock_config)
        await manager.initialize()
        
        try:
            # Mark adapter as not initialized
            manager.adapters['mock1'].initialized = False
            
            # Reload adapter
            success = await manager.reload_adapter('mock1')
            
            assert success is True
            assert manager.adapters['mock1'].initialized is True
            
        finally:
            await manager.cleanup()
    
    async def test_get_adapter_info(self, mock_config):
        """Test getting adapter information"""
        manager = AdapterManager(config=mock_config)
        await manager.initialize()
        
        try:
            info = manager.get_adapter_info()
            
            assert 'mock1' in info
            assert 'historical' in info
            
            assert info['mock1']['class'] == 'MockAdapter'
            assert info['mock1']['is_historical'] is False
            
            assert info['historical']['class'] == 'MockHistoricalAdapter'
            assert info['historical']['is_historical'] is True
            
        finally:
            await manager.cleanup()


if __name__ == "__main__":
    pytest.main([__file__, "-v"])

